#include <iostream>

#include <paxer/parser.h>
#include <paxer/driver.h>
#include <QString>
#include <boost/test/unit_test.hpp>
#include <boost/scoped_ptr.hpp>
#include <stack>

#if 1
BOOST_AUTO_TEST_CASE(Parsing_LIST_VECTOR_FUNCTION) {
    std::cout << "Intermediate..." <<  std::endl;
    CASpp::NodeRef nR0;
    CASpp::NodeRef nRa = CASpp::makeSymbolNodeRef("adf");
    CASpp::NodeRef nRcomma = CASpp::makeStringNodeRef(",");
    CASpp::NodeRef nRb = CASpp::makeSymbolNodeRef("bjd");
    CASpp::NodeRef nRc = CASpp::makeSymbolNodeRef("dsq");
    CASpp::NodeRef result;
    Paxer::Parser p((Paxer::DriverRef(new Paxer::DriverRef::element_type())));
    p.parse(Paxer::Parser::Token::LIST_BEGIN,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRa);
    p.parse(Paxer::Parser::Token::LIST_SEP,nRcomma);
    p.parse(Paxer::Parser::Token::Symbol,nRb);
    p.parse(Paxer::Parser::Token::LIST_END,nR0);
    result = p.endInput();
    BOOST_REQUIRE(result.get()!=0);
    BOOST_REQUIRE(result->isList());
    p.restart();
    result = p.endInput();
    BOOST_REQUIRE(result.get()==0);
    p.parse(Paxer::Parser::Token::LIST_BEGIN,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRa);
    p.parse(Paxer::Parser::Token::LIST_SEP,nRcomma);
    p.parse(Paxer::Parser::Token::Symbol,nRb);
    p.parse(Paxer::Parser::Token::LIST_SEP,nRcomma);
    p.parse(Paxer::Parser::Token::Symbol,nRc);
    p.parse(Paxer::Parser::Token::LIST_END,nR0);
    result = p.endInput();
    BOOST_REQUIRE(result.get()!=0);
    BOOST_REQUIRE(result->isList());
    std::cout << result->listRef()->longDescription() << std::endl;
    BOOST_REQUIRE((result->listRef()->back()==nRc).isTrue());
    result->listRef()->pop_back();
    BOOST_REQUIRE((result->listRef()->back()==nRb).isTrue());
    result->listRef()->pop_back();
    BOOST_REQUIRE((result->listRef()->back()==nRa).isTrue());

    p.restart();
    p.parse(Paxer::Parser::Token::VECTOR_BEGIN,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRa);
    p.parse(Paxer::Parser::Token::LIST_SEP,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRb);
    p.parse(Paxer::Parser::Token::LIST_SEP,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRc);
    p.parse(Paxer::Parser::Token::VECTOR_END,nR0);
    result = p.endInput();
    BOOST_REQUIRE(result.get()!=0);
    BOOST_REQUIRE(result->isVector());
    BOOST_REQUIRE((result->vectorRef()->back()==nRc).isTrue());
    result->vectorRef()->pop_back();
    BOOST_REQUIRE((result->vectorRef()->back()==nRb).isTrue());
    result->vectorRef()->pop_back();
    BOOST_REQUIRE((result->vectorRef()->back()==nRa).isTrue());

    p.restart();
    //p.parse(Paxer::Parser::Token::Symbol,nRa);
    p.parse(Paxer::Parser::Token::VECTOR_BEGIN,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRb);
    p.parse(Paxer::Parser::Token::LIST_SEP,nR0);
    p.parse(Paxer::Parser::Token::Symbol,nRc);
    p.parse(Paxer::Parser::Token::VECTOR_END,nR0);
    result = p.endInput();
    BOOST_REQUIRE(result.get()!=0);
    BOOST_REQUIRE(result->isVector());
    BOOST_REQUIRE((result->vectorRef()->back()==nRc).isTrue());
    result->vectorRef()->pop_back();
    BOOST_REQUIRE((result->vectorRef()->back()==nRb).isTrue());
    result->vectorRef()->pop_back();
    BOOST_REQUIRE((result->vectorRef()->back()==nRa).isTrue());

    std::cout << "Done" <<  std::endl;
}
#elif 0
BOOST_AUTO_TEST_CASE(ParsingIDENTIFIER) {
    std::cout <<  std::endl <<  std::endl << "Parsing IDENTIFIER" <<  std::endl;
    Paxer::DriverRef dR(new Paxer::DriverRef::element_type);
    BOOST_REQUIRE(CASpp::NodeRef()==dR->nodeRef());
    CASpp::NodeRef nR;
    Paxer::Parser p(dR);
    // Simulate a command line such as "x"
    nR = CASpp::makeSymbolNodeRef("x");
    p.parse(Paxer::Parser::Token::Symbol, nR);
    p.endOfInput();
    BOOST_REQUIRE(nR==dR->nodeRef());
    nR = CASpp::makeSymbolNodeRef("y");
    p.parse(Paxer::Parser::Token::Variable, nR);
    BOOST_REQUIRE_THROW(p.parse(Paxer::Parser::Token::Variable, nR),std::runtime_error);
    p.restart();
    p.parse(Paxer::Parser::Token::Symbol, nR);
    p.endOfInput();
    BOOST_REQUIRE(nR==dR->nodeRef());
    dR->prepareParse();
    BOOST_REQUIRE(CASpp::NodeRef()==dR->nodeRef());
    std::cout << "Done..." <<  std::endl;
}

#elif 0
BOOST_AUTO_TEST_CASE(Parsing1) {
    std::cout <<  std::endl <<  std::endl << "Parsing1" <<  std::endl;
    Paxer::DriverRef dR(new Paxer::Driver);
    Paxer::Parser p(dR);
    // Simulate a command line such as "x:=2+3"
    CASpp::NodeRef nR;
    nR = CASpp::makeStringNodeRef("x");
    p.parse(Paxer::Parser::Token::IDENTIFIER, nR);
    nR = CASpp::makeStringNodeRef(":=");
    p.parse(Paxer::Parser::Token::TAKES, nR);
    nR = CASpp::makeStringNodeRef("2");
    p.parse(Paxer::Parser::Token::NUMBER, nR);
    nR = CASpp::makeStringNodeRef("+");
    p.parse(Paxer::Parser::Token::PLUS, nR);
    nR = CASpp::makeStringNodeRef("3");
    p.parse(Paxer::Parser::Token::NUMBER, nR);
    std::cout << "DONE" << std::endl;
    p.parse(Paxer::Parser::Token::EndOfInput, nR);
    nR = p.nodeRef(0);
    if (nR.get()) {
        std::cout << "RESULT: " << nR->description() << std::endl;
    } else {
        std::cout << "NO RESULT: " << std::endl;
    }
}
#endif
